﻿using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace System.NETool;

/// <summary>
/// 心跳发送器类，用于定时发送心跳包。
/// </summary>
public class HeartSender : IDisposable
{
    private readonly UdpClient _client;
    private readonly IPEndPoint _endPoint;
    private bool _disposed;
    private readonly byte[] _heartData;
    private Timer _heartTimer;
    internal const string LocalIP = "127.0.0.1";
    private readonly TimeSpan _interval;

    /// <summary>
    /// 构造函数，初始化心跳发送器。
    /// </summary>
    /// <param name="port">目标端口</param>
    /// <param name="interval">心跳间隔</param>
    /// <param name="path">起始路径</param>
    public HeartSender(int port, TimeSpan interval, string path = "")
    {
        _interval = interval;
        _endPoint = new IPEndPoint(IPAddress.Parse(LocalIP), port);
        _client = new UdpClient();

        string processName = Process.GetCurrentProcess().ProcessName;
        _heartData = new byte[2 + processName.ToEnByteArray().Length];
        _heartData[0] = 0x01;
        _heartData[1] = (byte)_heartData.Length;
        processName.ToEnByteArray().CopyTo(_heartData, 2);

        if (SystemEx.IsLinux())
        {
            string file = "/etc/init.d/S99_" + processName;
            if (!File.Exists(file))
            {
                StringBuilder sb = new();
                sb.AppendLine("#!/bin/sh");
                sb.AppendLine("");
                sb.AppendLine("sleep 2");
                sb.AppendLine("cd /" + (path.IsValid() ? path : processName));
                sb.AppendLine("");
                sb.AppendLine("./" + processName + " &");
                File.WriteAllText(file, sb.ToString());
            }

            ProcessEx.RunProcess("chmod", "777 " + file);
        }

        Start();
    }

    /// <summary>
    /// 心跳定时器回调方法。
    /// </summary>
    /// <param name="theObj">回调参数</param>
    private void HeartTimerOutCallBack(object theObj)
    {
        if (_disposed) return;
        _client.Send(_heartData, _endPoint);
    }

    /// <summary>
    /// 释放资源。
    /// </summary>
    public void Dispose()
    {
        _disposed = true;
        CloseTimer();
        _client?.Dispose();
    }

    /// <summary>
    /// 关闭定时器。
    /// </summary>
    private void CloseTimer()
    {
        _heartTimer?.Change(-1, -1);
        _heartTimer?.Dispose();
    }

    /// <summary>
    /// 启动心跳发送器。
    /// </summary>
    public void Start()
    {
        CloseTimer();
        _heartTimer = new Timer(HeartTimerOutCallBack, null, _interval, _interval);
    }

    /// <summary>
    /// 停止心跳发送器。
    /// </summary>
    public void Stop()
    {
        CloseTimer();
        byte[] stopData = new byte[_heartData.Length];
        _heartData.CopyTo(stopData, 0);
        stopData[0] = 0x02;
        _client.Send(stopData, _endPoint);
    }

    /// <summary>
    /// 停止指定进程的心跳发送器。
    /// </summary>
    /// <param name="processName">进程名称</param>
    public void Stop(string processName)
    {
        if (Process.GetCurrentProcess().ProcessName.EqualsIgnoreCase(processName))
        {
            Stop();
        }
        else
        {
            byte[] stopData = new byte[2 + processName.ToEnByteArray().Length];
            stopData[0] = 0x02;
            stopData[1] = (byte)stopData.Length;
            processName.ToEnByteArray().CopyTo(stopData, 2);
            _client.Send(stopData, _endPoint);
        }
    }
}
